package com.icongyou.enterprise.talent_profile;

import com.icongyou.enterprise.data_aggregation.entity.CourseEntity;
import com.icongyou.enterprise.data_aggregation.entity.CourseStudentEntity;
import com.icongyou.enterprise.data_aggregation.entity.TenantEntity;
import com.icongyou.enterprise.data_aggregation.entity.UserEntity;
import com.icongyou.enterprise.data_aggregation.entity.vo.StudentTopSubmissionDetailVO;
import com.icongyou.enterprise.data_aggregation.entity.vo.StudentTopSubmissionSimpleVO;
import com.icongyou.enterprise.data_aggregation.mapper.DataAggregationMapper;
import com.icongyou.enterprise.data_aggregation.service.DataAggregationService;
import com.icongyou.enterprise.talent_profile.entity.vo.*;
import com.icongyou.enterprise.talent_profile.service.ProfileServiceImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class ProfileServiceImplTest {

    @Mock
    private DataAggregationService dataAggregationService;

    @Mock
    private DataAggregationMapper dataAggregationMapper;

    @InjectMocks
    private ProfileServiceImpl profileService;

    private String studentId;
    private String courseId;
    private String submissionId;
    private UserEntity student;
    private TenantEntity tenant;
    private CourseEntity course;
    private CourseStudentEntity courseStudent;

    @BeforeEach
    void setUp() {
        studentId = "STU001";
        courseId = "COURSE001";
        submissionId = "SUBM001";

        // 初始化测试数据
        student = new UserEntity();
        student.setId(studentId);
        student.setRealName("张三");
        student.setTenantId("TENANT001");

        tenant = new TenantEntity();
        tenant.setId("TENANT001");
        tenant.setTenantName("测试大学");

        course = new CourseEntity();
        course.setCourseId(courseId);
        course.setCourseName("软件工程");
        course.setAcademicYear("2023-2024");
        course.setCourseIntro("软件工程导论课程");
        course.setStudentCount(50);
        course.setTeacherId("TEACHER001");

        courseStudent = new CourseStudentEntity();
        courseStudent.setStudentId(studentId);
        courseStudent.setCourseId(courseId);
        courseStudent.setScore(new BigDecimal("85.5"));
        courseStudent.setCourseRank(10);
        courseStudent.setEnrollmentTime(LocalDateTime.now());
    }

    @Test
    void getStudentBasicInfo_WhenStudentExists_ShouldReturnBasicInfo() {
        // Arrange
        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getTenantById(student.getTenantId())).thenReturn(tenant);

        // Act
        StudentBasicVO result = profileService.getStudentBasicInfo(studentId);

        // Assert
        assertNotNull(result);
        assertEquals(studentId, result.getStudentId());
        assertEquals(student.getRealName(), result.getRealName());
        assertEquals(tenant.getTenantName(), result.getSchoolName());

        verify(dataAggregationService).getStudentById(studentId);
        verify(dataAggregationService).getTenantById(student.getTenantId());
    }

    @Test
    void getStudentBasicInfo_WhenStudentNotExists_ShouldThrowException() {
        // Arrange
        when(dataAggregationService.getStudentById(studentId)).thenReturn(null);

        // Act & Assert
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> profileService.getStudentBasicInfo(studentId));
        assertEquals("学生不存在", exception.getMessage());

        verify(dataAggregationService).getStudentById(studentId);
        verify(dataAggregationService, never()).getTenantById(anyString());
    }

    @Test
    void getLearningOverview_WhenStudentHasNoCourses_ShouldReturnEmptyResponse() {
        // Arrange
        Integer page = 1;
        Integer size = 10;

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(Collections.emptyList());

        // Act
        LearningOverviewRespVO result = profileService.getLearningOverview(studentId, page, size);

        // Assert
        assertNotNull(result);
        assertEquals(studentId, result.getStudentId());
        assertEquals(student.getRealName(), result.getRealName());
        assertTrue(result.getCoursePerformance().isEmpty());
        assertNotNull(result.getPagination());
        assertEquals(0, result.getPagination().getTotal());

        verify(dataAggregationService).getStudentById(studentId);
        verify(dataAggregationService).getStudentCourse(studentId);
        verify(dataAggregationService, never()).getCourseById(anyString());
    }

    @Test
    void getLearningOverview_WhenStudentNotExists_ShouldThrowException() {
        // Arrange
        Integer page = 1;
        Integer size = 10;

        when(dataAggregationService.getStudentById(studentId)).thenReturn(null);

        // Act & Assert
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> profileService.getLearningOverview(studentId, page, size));
        assertEquals("学生不存在", exception.getMessage());

        verify(dataAggregationService).getStudentById(studentId);
        verify(dataAggregationService, never()).getStudentCourse(anyString());
    }

    @Test
    void getLearningOverview_WithPagination_ShouldReturnCorrectPage() {
        // Arrange
        Integer page = 1;
        Integer size = 2;

        CourseStudentEntity courseStudent2 = new CourseStudentEntity();
        courseStudent2.setStudentId(studentId);
        courseStudent2.setCourseId("COURSE002");
        courseStudent2.setScore(new BigDecimal("90.0"));
        courseStudent2.setCourseRank(5);

        CourseEntity course2 = new CourseEntity();
        course2.setCourseId("COURSE002");
        course2.setCourseName("数据库原理");
        course2.setAcademicYear("2022-2023");

        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudent, courseStudent2);

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);
        when(dataAggregationService.getCourseById("COURSE002")).thenReturn(course2);

        // Act
        LearningOverviewRespVO result = profileService.getLearningOverview(studentId, page, size);

        // Assert
        assertNotNull(result);
        assertEquals(2, result.getCoursePerformance().size());
        assertEquals(1, result.getPagination().getPage());
        assertEquals(2, result.getPagination().getSize());
        assertEquals(2, result.getPagination().getTotal());
        assertEquals(1, result.getPagination().getTotalPages());
    }

    @Test
    void getStudentCourses_WhenStudentHasCourses_ShouldReturnCourseList() {
        // Arrange
        UserEntity teacher = new UserEntity();
        teacher.setId("TEACHER001");
        teacher.setRealName("李老师");

        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudent);

        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);
        when(dataAggregationService.getUserById(course.getTeacherId())).thenReturn(teacher);

        // Act
        List<StudentCourseVO> result = profileService.getStudentCourses(studentId);

        // Assert
        assertNotNull(result);
        assertEquals(1, result.size());

        StudentCourseVO courseVO = result.get(0);
        assertEquals(courseId, courseVO.getCourseId());
        assertEquals(course.getCourseName(), courseVO.getCourseName());
        assertEquals(course.getAcademicYear(), courseVO.getAcademicYear());
        assertEquals(teacher.getRealName(), courseVO.getTeacherName());
        assertEquals(10, courseVO.getCourseRank());
        assertEquals(85.5, courseVO.getScore().doubleValue());

        verify(dataAggregationService).getStudentCourse(studentId);
        verify(dataAggregationService).getCourseById(courseId);
        verify(dataAggregationService).getUserById(course.getTeacherId());
    }

    @Test
    void getStudentCourses_WhenStudentHasNoCourses_ShouldReturnEmptyList() {
        // Arrange
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(Collections.emptyList());

        // Act
        List<StudentCourseVO> result = profileService.getStudentCourses(studentId);

        // Assert
        assertNotNull(result);
        assertTrue(result.isEmpty());
        verify(dataAggregationService).getStudentCourse(studentId);
        verify(dataAggregationService, never()).getCourseById(anyString());
    }

    @Test
    void getStudentTopSubmissionsSimple_ShouldReturnSubmissionList() {
        // Arrange
        List<StudentTopSubmissionSimpleVO> expectedSubmissions = Arrays.asList(
                new StudentTopSubmissionSimpleVO(),
                new StudentTopSubmissionSimpleVO()
        );

        when(dataAggregationMapper.getTopSubmissionsSimple(studentId)).thenReturn(expectedSubmissions);

        // Act
        List<StudentTopSubmissionSimpleVO> result = profileService.getStudentTopSubmissionsSimple(studentId);

        // Assert
        assertNotNull(result);
        assertEquals(2, result.size());
        verify(dataAggregationMapper).getTopSubmissionsSimple(studentId);
    }

    @Test
    void getStudentTopSubmissionsSimple_WhenExceptionOccurs_ShouldThrowRuntimeException() {
        // Arrange
        when(dataAggregationMapper.getTopSubmissionsSimple(studentId))
                .thenThrow(new RuntimeException("Database error"));

        // Act & Assert
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> profileService.getStudentTopSubmissionsSimple(studentId));
        assertEquals("获取核心成果失败", exception.getMessage());
        assertNotNull(exception.getCause());

        verify(dataAggregationMapper).getTopSubmissionsSimple(studentId);
    }

    @Test
    void getStudentTopSubmissionsDetail_ShouldReturnDetailList() {
        // Arrange
        List<StudentTopSubmissionDetailVO> expectedSubmissions = Arrays.asList(
                new StudentTopSubmissionDetailVO(),
                new StudentTopSubmissionDetailVO()
        );

        when(dataAggregationMapper.getTopSubmissionsDetail(studentId)).thenReturn(expectedSubmissions);

        // Act
        List<StudentTopSubmissionDetailVO> result = profileService.getStudentTopSubmissionsDetail(studentId);

        // Assert
        assertNotNull(result);
        assertEquals(2, result.size());
        verify(dataAggregationMapper).getTopSubmissionsDetail(studentId);
    }

    @Test
    void getSubmissionDetailById_ShouldReturnSubmissionDetail() {
        // Arrange
        SubmissionDetailVO expectedDetail = new SubmissionDetailVO();
        when(dataAggregationMapper.getSubmissionDetailById(submissionId)).thenReturn(expectedDetail);

        // Act
        SubmissionDetailVO result = profileService.getSubmissionDetailById(submissionId);

        // Assert
        assertNotNull(result);
        assertEquals(expectedDetail, result);
        verify(dataAggregationMapper).getSubmissionDetailById(submissionId);
    }

    @Test
    void getTopSubmissionByStudentAndCourse_WhenValidInput_ShouldReturnTopSubmission() {
        // Arrange
        CourseTopSubmissionVO expectedSubmission = new CourseTopSubmissionVO();
        List<CourseStudentEntity> studentCourses = Arrays.asList(courseStudent);

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(studentCourses);
        when(dataAggregationMapper.getTopSubmissionByStudentAndCourse(studentId, courseId))
                .thenReturn(expectedSubmission);

        // Act
        CourseTopSubmissionVO result = profileService.getTopSubmissionByStudentAndCourse(studentId, courseId);

        // Assert
        assertNotNull(result);
        assertEquals(expectedSubmission, result);

        verify(dataAggregationService).getStudentById(studentId);
        verify(dataAggregationService).getCourseById(courseId);
        verify(dataAggregationService).getStudentCourse(studentId);
        verify(dataAggregationMapper).getTopSubmissionByStudentAndCourse(studentId, courseId);
    }

    @Test
    void getTopSubmissionByStudentAndCourse_WhenStudentNotExists_ShouldThrowException() {
        // Arrange
        when(dataAggregationService.getStudentById(studentId)).thenReturn(null);

        // Act & Assert
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> profileService.getTopSubmissionByStudentAndCourse(studentId, courseId));
        assertEquals("获取最高得分提交失败: 学生不存在", exception.getMessage());

        verify(dataAggregationService).getStudentById(studentId);
        verify(dataAggregationService, never()).getCourseById(anyString());
        verify(dataAggregationService, never()).getStudentCourse(anyString());
        verify(dataAggregationMapper, never()).getTopSubmissionByStudentAndCourse(anyString(), anyString());
    }

    @Test
    void getTopSubmissionByStudentAndCourse_WhenCourseNotExists_ShouldThrowException() {
        // Arrange
        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(null);

        // Act & Assert
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> profileService.getTopSubmissionByStudentAndCourse(studentId, courseId));
        assertEquals("获取最高得分提交失败: 课程不存在", exception.getMessage());

        verify(dataAggregationService).getStudentById(studentId);
        verify(dataAggregationService).getCourseById(courseId);
        verify(dataAggregationService, never()).getStudentCourse(anyString());
        verify(dataAggregationMapper, never()).getTopSubmissionByStudentAndCourse(anyString(), anyString());
    }

    @Test
    void getTopSubmissionByStudentAndCourse_WhenStudentNotEnrolled_ShouldThrowException() {
        // Arrange
        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(Collections.emptyList());

        // Act & Assert
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> profileService.getTopSubmissionByStudentAndCourse(studentId, courseId));
        assertEquals("获取最高得分提交失败: 学生未选修该课程", exception.getMessage());

        verify(dataAggregationService).getStudentById(studentId);
        verify(dataAggregationService).getCourseById(courseId);
        verify(dataAggregationService).getStudentCourse(studentId);
        verify(dataAggregationMapper, never()).getTopSubmissionByStudentAndCourse(anyString(), anyString());
    }

    @Test
    void getLearningOverview_WhenCourseHasNullScore_ShouldHandleGracefully() {
        // Arrange
        Integer page = 1;
        Integer size = 10;

        CourseStudentEntity courseStudentWithNullScore = new CourseStudentEntity();
        courseStudentWithNullScore.setStudentId(studentId);
        courseStudentWithNullScore.setCourseId(courseId);
        courseStudentWithNullScore.setScore(null);
        courseStudentWithNullScore.setCourseRank(15);

        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudentWithNullScore);

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);

        // Act
        LearningOverviewRespVO result = profileService.getLearningOverview(studentId, page, size);

        // Assert
        assertNotNull(result);
        assertEquals(1, result.getCoursePerformance().size());

        CoursePerformanceSimpleVO performanceVO = result.getCoursePerformance().get(0);
        assertNull(performanceVO.getTotalScore());
        assertEquals(15, performanceVO.getClassRanking());
    }

    @Test
    void getLearningOverview_WhenCourseNotFound_ShouldSkipCourse() {
        // Arrange
        Integer page = 1;
        Integer size = 10;

        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudent);

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(null); // 课程不存在

        // Act
        LearningOverviewRespVO result = profileService.getLearningOverview(studentId, page, size);

        // Assert
        assertNotNull(result);
        assertTrue(result.getCoursePerformance().isEmpty()); // 应该跳过不存在的课程
        verify(dataAggregationService).getCourseById(courseId);
    }

    @Test
    void getLearningOverview_WithMultiplePages_ShouldReturnCorrectSecondPage() {
        // Arrange
        Integer page = 2;
        Integer size = 1;

        CourseStudentEntity courseStudent2 = new CourseStudentEntity();
        courseStudent2.setStudentId(studentId);
        courseStudent2.setCourseId("COURSE002");
        courseStudent2.setScore(new BigDecimal("90.0"));
        courseStudent2.setCourseRank(5);

        CourseStudentEntity courseStudent3 = new CourseStudentEntity();
        courseStudent3.setStudentId(studentId);
        courseStudent3.setCourseId("COURSE003");
        courseStudent3.setScore(new BigDecimal("88.0"));
        courseStudent3.setCourseRank(7);

        CourseEntity course2 = new CourseEntity();
        course2.setCourseId("COURSE002");
        course2.setCourseName("数据库原理");
        course2.setAcademicYear("2023-2024");

        CourseEntity course3 = new CourseEntity();
        course3.setCourseId("COURSE003");
        course3.setCourseName("操作系统");
        course3.setAcademicYear("2022-2023");

        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudent, courseStudent2, courseStudent3);

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);
        when(dataAggregationService.getCourseById("COURSE002")).thenReturn(course2);
        when(dataAggregationService.getCourseById("COURSE003")).thenReturn(course3);

        // Act
        LearningOverviewRespVO result = profileService.getLearningOverview(studentId, page, size);

        // Assert
        assertNotNull(result);
        assertEquals(1, result.getCoursePerformance().size()); // 第2页只有1条数据
        assertEquals(2, result.getPagination().getPage());
        assertEquals(3, result.getPagination().getTotal());
        assertEquals(3, result.getPagination().getTotalPages());
    }

    @Test
    void getLearningOverview_WhenPageExceedsTotalPages_ShouldReturnEmptyList() {
        // Arrange
        Integer page = 10; // 超出范围的页码
        Integer size = 10;

        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudent);

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);

        // Act
        LearningOverviewRespVO result = profileService.getLearningOverview(studentId, page, size);

        // Assert
        assertNotNull(result);
        assertTrue(result.getCoursePerformance().isEmpty());
        assertEquals(10, result.getPagination().getPage());
    }

    @Test
    void getLearningOverview_WithCoursesHavingNullAcademicYear_ShouldSortProperly() {
        // Arrange
        Integer page = 1;
        Integer size = 10;

        CourseStudentEntity courseStudent2 = new CourseStudentEntity();
        courseStudent2.setStudentId(studentId);
        courseStudent2.setCourseId("COURSE002");
        courseStudent2.setScore(new BigDecimal("90.0"));

        CourseEntity courseWithNullYear = new CourseEntity();
        courseWithNullYear.setCourseId("COURSE002");
        courseWithNullYear.setCourseName("测试课程");
        courseWithNullYear.setAcademicYear(null); // 学年为null

        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudent, courseStudent2);

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);
        when(dataAggregationService.getCourseById("COURSE002")).thenReturn(courseWithNullYear);

        // Act
        LearningOverviewRespVO result = profileService.getLearningOverview(studentId, page, size);

        // Assert
        assertNotNull(result);
        assertEquals(2, result.getCoursePerformance().size());
        // 验证排序没有抛出异常
    }

    @Test
    void getStudentCourses_WhenCourseNotFound_ShouldReturnVOWithPartialInfo() {
        // Arrange
        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudent);

        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(null); // 课程不存在

        // Act
        List<StudentCourseVO> result = profileService.getStudentCourses(studentId);

        // Assert
        assertNotNull(result);
        assertEquals(1, result.size());
        StudentCourseVO courseVO = result.get(0);
        assertEquals(courseId, courseVO.getCourseId());
        assertNull(courseVO.getCourseName()); // 课程名为null
        assertEquals(85.5, courseVO.getScore().doubleValue());

        verify(dataAggregationService, never()).getUserById(anyString());
    }

    @Test
    void getStudentCourses_WhenTeacherNotFound_ShouldReturnVOWithoutTeacherName() {
        // Arrange
        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudent);

        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);
        when(dataAggregationService.getUserById(course.getTeacherId())).thenReturn(null); // 教师不存在

        // Act
        List<StudentCourseVO> result = profileService.getStudentCourses(studentId);

        // Assert
        assertNotNull(result);
        assertEquals(1, result.size());
        StudentCourseVO courseVO = result.get(0);
        assertEquals(course.getCourseName(), courseVO.getCourseName());
        assertNull(courseVO.getTeacherName()); // 教师名为null
    }

    @Test
    void getStudentCourses_WhenEnrollmentTimeIsNull_ShouldReturnNullEnrollmentTime() {
        // Arrange
        CourseStudentEntity courseStudentWithNullTime = new CourseStudentEntity();
        courseStudentWithNullTime.setStudentId(studentId);
        courseStudentWithNullTime.setCourseId(courseId);
        courseStudentWithNullTime.setScore(new BigDecimal("85.5"));
        courseStudentWithNullTime.setEnrollmentTime(null); // 选课时间为null

        UserEntity teacher = new UserEntity();
        teacher.setId("TEACHER001");
        teacher.setRealName("李老师");

        List<CourseStudentEntity> courseStudents = Arrays.asList(courseStudentWithNullTime);

        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);
        when(dataAggregationService.getUserById(course.getTeacherId())).thenReturn(teacher);

        // Act
        List<StudentCourseVO> result = profileService.getStudentCourses(studentId);

        // Assert
        assertNotNull(result);
        assertEquals(1, result.size());
        assertNull(result.get(0).getEnrollmentTime());
    }

    @Test
    void getStudentTopSubmissionsDetail_WhenExceptionOccurs_ShouldThrowRuntimeException() {
        // Arrange
        when(dataAggregationMapper.getTopSubmissionsDetail(studentId))
                .thenThrow(new RuntimeException("Database error"));

        // Act & Assert
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> profileService.getStudentTopSubmissionsDetail(studentId));
        assertEquals("获取核心成果详情失败", exception.getMessage());
        assertNotNull(exception.getCause());
    }

    @Test
    void getSubmissionDetailById_WhenExceptionOccurs_ShouldThrowRuntimeException() {
        // Arrange
        when(dataAggregationMapper.getSubmissionDetailById(submissionId))
                .thenThrow(new RuntimeException("Database error"));

        // Act & Assert
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> profileService.getSubmissionDetailById(submissionId));
        assertEquals("获取提交详情失败", exception.getMessage());
        assertNotNull(exception.getCause());
    }

    @Test
    void getTopSubmissionByStudentAndCourse_WhenMapperThrowsException_ShouldWrapException() {
        // Arrange
        List<CourseStudentEntity> studentCourses = Arrays.asList(courseStudent);

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getCourseById(courseId)).thenReturn(course);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(studentCourses);
        when(dataAggregationMapper.getTopSubmissionByStudentAndCourse(studentId, courseId))
                .thenThrow(new RuntimeException("Mapper error"));

        // Act & Assert
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> profileService.getTopSubmissionByStudentAndCourse(studentId, courseId));
        assertTrue(exception.getMessage().contains("获取最高得分提交失败"));
    }

    @Test
    void getLearningOverview_WithBothNullAndValidAcademicYears_ShouldSortCorrectly() {
        // Arrange
        Integer page = 1;
        Integer size = 10;

        CourseStudentEntity cs1 = new CourseStudentEntity();
        cs1.setStudentId(studentId);
        cs1.setCourseId("COURSE001");
        cs1.setScore(new BigDecimal("85.0"));

        CourseStudentEntity cs2 = new CourseStudentEntity();
        cs2.setStudentId(studentId);
        cs2.setCourseId("COURSE002");
        cs2.setScore(new BigDecimal("90.0"));

        CourseEntity c1 = new CourseEntity();
        c1.setCourseId("COURSE001");
        c1.setCourseName("课程1");
        c1.setAcademicYear(null);

        CourseEntity c2 = new CourseEntity();
        c2.setCourseId("COURSE002");
        c2.setCourseName("课程2");
        c2.setAcademicYear(null);

        List<CourseStudentEntity> courseStudents = Arrays.asList(cs1, cs2);

        when(dataAggregationService.getStudentById(studentId)).thenReturn(student);
        when(dataAggregationService.getStudentCourse(studentId)).thenReturn(courseStudents);
        when(dataAggregationService.getCourseById("COURSE001")).thenReturn(c1);
        when(dataAggregationService.getCourseById("COURSE002")).thenReturn(c2);

        // Act
        LearningOverviewRespVO result = profileService.getLearningOverview(studentId, page, size);

        // Assert
        assertNotNull(result);
        assertEquals(2, result.getCoursePerformance().size());
        // 两个都为null时，应该返回0（相等），不抛出异常
    }
}
